<?php if(!defined('OCTOMS')){header('HTTP/1.1 403');die('{"error":"forbidden"}');}
/*
 * @package       OctoMS.com
 * @subpackage    DesignJotter
 * @copyright     Copyright 2011, Valentino-Jivko Radosavlevici (http://valentino.radosavlevici.com)
 * @license       GPL v3.0 (http://www.gnu.org/licenses/gpl-3.0.txt)
 * 
 * Redistributions of files must retain the above copyright notice.
 * 
 * @since         OctoMS.com 0.0.1
 */
	
	/*
	 * Template library for the OctoMS.com Content Management System
	 * 
	 * @package OctoMS.com
	 * @version 0.1
	 * 
	 * @author Valentino-Jivko Radosavlevici
	 */
	class template_l
	{		
		/*
		 * Page data
		 */
		var $data;
		
		/*
		 * Try catch procedure bug
		 */
		var $bug = array('status'=>true,'message','code');
		
		/*
		 * The script root
		 */
		var $scriptroot = 'template';
		
		/*
		 * Load in footer?
		 */
		var $infooter = true;
		
		/**
		 * Prevent errors if the user calls an invalid method
		 * 
		 * @param string $method
		 * @param array $args
		 * @return null
		 * @package OctoMS.com
		 * 
		 * @author Valentino-Jivko Radosavlevici
		 */
		function __call($method='',$args=array())
		{
			// Don't return an error if the user calls the wrong function
			return;
		}// end function __call()
		
		/**
		 * Don't display errors if the user accidentally tries to prin $this
		 * 
		 * @return null
		 * @package OctoMS.com
		 * 
		 * @author Valentino-Jivko Radosavlevici
		 */
		function __toString()
		{
			// Prevent errors from showing
			return '';
			
		}// end function __toString()
		
		/**
		 * Load the template, set the content and exit
		 * 
		 * @return void
		 * @package OctoMS.com
		 * 
		 * @author Valentino-Jivko Radosavlevici
		 */
		function _flush()
		{
			// Don't display the template if the user requested it
			if ($this->_conf('whitescreen') == TRUE) return;
			
			// Set the content
			$this->_set('content',ob_get_clean());

			// Load the template file
			if (file_exists($f=APP_TPL.DS.$this->_conf('page').'.tpl'))
			{
				require_once $f;
			}
			else 
			{
				$this->content();
			}
		}// end function _flush()
		
		/**
		 * OctoMS.com Admin API
		 * 
		 * @example 
		 * // Set the status message
		 * {template}->_api('Update completed.');
		 * // Set an error status message (appended)
		 * {template}->_api('Update failed.',false);
		 * // Replace previously set status messages
		 * {template}->_api('Final status.',false,false);
		 * // Set the list of filters to apply to the content
		 * {template}->_api(array('f1','f2'));
		 * // Replace previously set filters
		 * {template}->_api(array('f1','f2'),false);
		 * 
		 * @param mixed $a - array for filters, string or bool for status msg.
		 * @param bool $b - type of status message/append the filters?
		 * @param bool $append - append the message?
		 * @return {template}
		 * @package OctoMS.com
		 * 
		 * @author Valentino-Jivko Radosavlevici
		 */
		function _api($a=NULL,$b=TRUE,$append=TRUE)
		{
			// The first argument is mandatory
			if (empty($a)) return $this;
			
			// Set the status message
			if (is_string($a))
			{
				// Status already set?
				if (is_null($status = $this->_get1('api_status')) || !$append)
				{
					// Set the status the first time
					$this->_set(
						'api_status',
						array(
							$a,
							$b
						)
					);
				}
				else 
				{
					// Append to the status message and change the status type
					$this->_set(
						'api_status',
						array(
							$status[0].' '.$a,
							$status[1] && $b
						)
					);
				}
				
				// Set the session flash key
				if (!isset($_POST['#*#'])){octoms('session',OMS_CL)->flash_set('api_status',$this->_get1('api_status'));}
			}
			// Set the filters
			elseif (is_array($a))
			{
				// Filters already set?
				if (is_null($filters = $this->_get1('api_filters')) || !$b)
				{
					// Set the filters for the first time
					$this->_set(
						'api_filters',
						$a
					);
				}
				else 
				{
					// Append to the filters list
					$this->_set(
						'api_filters',
						array_merge($filters,$a)
					);
				}
				
				// Set the session flash key
				if (!isset($_POST['#*#'])){octoms('session',OMS_CL)->flash_set('api_filters',$this->_get1('api_filters'));}
			}
			
			// Return self
			return $this;
		}// end function _api()
		
		/**
		 * Set or get the API request content
		 * 
		 * @example 
		 * // The _content_ parameter will be populated
		 * {template}->_api_cnt('a new page element');
		 * // Get the data sent as the API content
		 * {template}->_api_cnt();
		 * 
		 * @param string $str
		 * @return {template}/mixed - currently set value or NULL if not set
		 * @package OctoMS.com
		 * 
		 * @author Valentino-Jivko Radosavlevici
		 */
		function _api_cnt($str=null)
		{
			// Return the content?
			if (is_null($str))
			{
				return $this->_get1('api_content');
			}
			else 
			{
				// Content already set?
				if (is_null($content = $this->_get1('api_content')))
				{
					// Set the session flash key
					if (!isset($_POST['#*#'])){octoms('session',OMS_CL)->flash_set('api_content',$str);}
					
					// Set the content for the first time.
					return $this->_set(
						'api_content',
						$str
					);
				}
				else 
				{
					// Array?
					if (is_array($content) || is_object($content))
					{
						// Make sure it is an array
						$content = object_to_array($content);
						
						// Append the content
						$content = array_merge($content,(array)$str);
					}
					// String
					else 
					{
						if (is_array($str))
						{
							$content = array_merge((array)$content,$str);
						}
						else 
						{
							$content .= $str;
						}
					}
					
					// Set the session flash key
					if (!isset($_POST['#*#'])){octoms('session',OMS_CL)->flash_set('api_content',$content);}
					
					// Append content to the result; no spaces;
					return $this->_set(
						'api_content',
						$content
					);
				}
			}
		}// end function _api_cnt()
		
		/**
		 * Append; data storage
		 * 
		 * @example 
		 * // Append $x to the 'y' key
		 * {template}->_app('y',$x);
		 * 
		 * @param string $key
		 * @param mixed $value
		 * @return {template}
		 * @package OctoMS.com
		 * 
		 * @author Valentino-Jivko Radosavlevici
		 */
		function _app($key='',$value=NULL)
		{
			if ($key == '__conf__') return $this;
			
			// Allow any number of values to be sent
			$values = func_get_args();array_shift($values);if(count($values)==0)$values=array(NULL);
			
			foreach ($values AS $value)
			{
				if (!isset($this->data[$key]) && strlen($key)>0)
				{
					$this->_set($key,$value);
				}
				elseif (strlen($key)>0)
				{
					$get = $this->_get($key);
					$get[] = $value;
					$this->data[$key] = $get;
				}
			}
			return $this;
		}// end function _app()
		
		/**
		 * Try-catch procedure; Exception
		 * 
		 * @example 
		 * // Issue a template exception (catchable by trap trap/snap functions)
		 * {template}->_bug('Some exception',10);
		 * 
		 * @param string $message
		 * @param string/int $code
		 * @return false
		 * @package OctoMS.com
		 * 
		 * @author Valentino-Jivko Radosavlevici
		 */
		function _bug($message='',$code='')
		{
			$this->bug = array('status'=>false,'message'=>$message,'code'=>$code);
			return FALSE;
		}// end function _bug()
		
		/**
		 * Clean; data storage
		 * 
		 * @example 
		 * // Remove the 'abc' key
		 * {template}->_clean('abc');
		 * 
		 * @param string $key
		 * @return {template}
		 * @package OctoMS.com
		 * 
		 * @author Valentino-Jivko Radosavlevici
		 */
		function _cln($key='')
		{
			if (!empty($key) && isset($this->data[$key]) && $key != '__conf__')
			{
				unset($this->data[$key]);
			}
			return $this;
		}// end function _cln()

		/**
		 * Set or get configuration parameters; 
		 * allowed values are [whitescreen, template, method, addon, area, page]
		 * 
		 * @example 
		 * // Set the page
		 * {template}->_conf('page','pagex');
		 * // Get the page
		 * {template}->_conf('page');
		 * 
		 * @param string $key
		 * @param mixed $value
		 * @return {template}/mixed-the value
		 * @package OctoMS.com
		 * 
		 * @author Valentino-Jivko Radosavlevici
		 */
		function _conf($key=NULL)
		{
			// Special config keys
			if (!in_array($key, array('whitescreen','method','page'))) return false;
			
			// Function arguments
			$args = func_get_args();
			
			// Set a value
			if (isset($args[1]))
			{
				$this->data['__conf__'][$key] = $args[1]; 
				return $this;
			}
			// Retrieve a value
			else
			{
				return isset($this->data['__conf__'][$key])?$this->data['__conf__'][$key]:NULL;
			}
		}// end function _conf()
		
		/**
		 * Get; data storage
		 * 
		 * @example 
		 * // Get the contents of the 'y' key
		 * {template}->_get('y')
		 * 
		 * @param string $key
		 * @return array of mixed values / null if not found
		 * @package OctoMS.com
		 * 
		 * @author Valentino-Jivko Radosavlevici
		 */
		function _get($key='')
		{
			if (strlen($key)>0 && $key != '__conf__')
			{
				return isset($this->data[$key])?$this->data[$key]:NULL;
			}
			else 
			{
				return NULL;
			}
		}// end function _get()
		
		/**
		 * Get 1 value; data storage
		 * 
		 * @example 
		 * // Instead of getting array(0=>"data") you get "data"
		 * {template}->_get1('y'); # see {template}->_get()
		 * 
		 * @param string $key
		 * @return mixed/null
		 * @package OctoMS.com
		 * 
		 * @author Valentino-Jivko Radosavlevici
		 */
		function _get1($key='')
		{
			return (is_null($r = $this->_get($key))?null:$r[0]);
			
		}// end function _get1()
		
		/**
		 * Redirect template function
		 * 
		 * @example 
		 * // Set a Location header
		 * {template}->_r('admin')
		 * 
		 * @param string $page
		 * @return void
		 * @package OctoMS.com
		 * 
		 * @author Valentino-Jivko Radosavlevici
		 */
		function _r($page='')
		{
			if (!debugging() || ENVIRONMENT)
			{
				@ob_end_clean();
				@header(
					'location:'.str_replace(
						array(
							"\r\n",
							"\r",
							"\n"
						),
						'',
						baseurl($page)
					)
				);
			}
			else 
			{
				header('octoms-redirect:'.baseurl($page));
			}
			exit();
		}// end function _r()
		
		/**
		 * Set; data storage
		 * 
		 * @example 
		 * // Set the 'y' key to $x
		 * {template}->_set('y',$x);
		 * 
		 * @param string $key
		 * @param mixed $value
		 * @return {template}
		 * @package OctoMS.com
		 * 
		 * @author Valentino-Jivko Radosavlevici
		 */
		function _set($key='',$value=NULL)
		{		
			if (strlen($key)>0 && $key != '__conf__')
			{
				$this->data[$key] = array($value);
			}
			return $this;
		}// end function _set()
		
		/**
		 * Shortcode helper
		 * 
		 * @example 
		 * 
		 * @param 
		 * @return 
		 * 
		 * @author Valentino-Jivko Radosavlevici
		 */
		function _shortcode()
		{
			if (count($args = func_get_args())>2)
			{
				// Get the widget
				$widget = $args[2];
				
				// Parse the arguments
				if (!empty($args[0]) && count($args[0])>0) 
				{
					// Get the method
					$method = array_shift($args[0]);
					$method = is_null($method)?'index':$method;
					
					// Parse the arguments
					foreach ($args[0] AS $key => $value)
					{
						if ($value === 'true') $args[0][$key] = true;
						if ($value === 'false') $args[0][$key] = false;
						if ($value === 'null' || $value === '') $args[0][$key] = null;
						if (false !== strpos($value, '{') && false !== strpos($value, '}'))
						{
							if (null !== $json = @json_decode(str_replace('&quot;', '"', $value)))
							{
								$args[0][$key] = (array)$json;
							}
						}
					}
				}
				// Set the arguments to null
				else
				{
					$args[0] = null;
				}
				
				// Start the output buffer
				ob_start();
				
				// Call the widget
				$res0 = $this->widget($widget,$method,$args[0],$args[1]);
				
				// Get the result
				$res1 = ob_get_clean();
			
				// Get the error message
				if (isset($this->bug['status']) && !$this->bug['status']) 
				{	
					$res1 = $this->bug['message'];
				}
				
				// Return the result
				if (!empty($res1))
				{
					return $res1;
				}
				elseif (isset($res0))
				{
					return $res0;
				}

				// Nothing to display
				return null;
			}
			else 
			{
				return null;
			}
			
		}// end function _shortcode()
		
		/**
		 * Add shortcodes
		 * 
		 * @param string $str
		 * @return string - the result of the shortcode
		 * @package OctoMS.com
		 * 
		 * @author Valentino-Jivko Radosavlevici
		 */
		function _shortcodes()
		{
			// Get the list of widgets
			$folder = APP_ROOT.DS.'stages'.DS.'widgets';
			$w = array();
			if ( false !== $dir = @opendir( $folder ) ) {
				while (($file = readdir( $dir ) ) !== false ) 
				{
					if ( in_array($file, array('.', '..') ) )continue;
					if ( is_dir( $folder . '/' . $file )  && strpos($file, '_') !== 0) 
					{
						$w[] = $file;
					}
				}
			}
			@closedir( $dir );
			
			// Add the shortcodes
			if (count($w)>0)
			{
				foreach ($w AS $widget)
				{
					add_shortcode($widget, array($this,'_shortcode'));
				}
			}
			
		}// end function _shortcodes()
		
		/**
		 * Display the page's content
		 * 
		 * @example 
		 * // Display the page content
		 * {template}->content();
		 * 
		 * @param string $content
		 * @return $this
		 * @package OctoMS.com
		 * 
		 * @author Valentino-Jivko Radosavlevici
		 */
		function content()
		{
			print $this->_get1('content');
			return $this;
		}// end function content()
		
		/**
		 * Enqueue WordPress CSS scripts
		 * 
		 * @param array $css
		 * @return $this
		 * @package OctoMS.com
		 * 
		 * @author Valentino-Jivko Radosavlevici
		 */
		function css()
		{
			// Enqueue scripts one by one
			if (count($args = func_get_args())>0)
			{
				foreach ($args AS $css)
				{
					wp_enqueue_style(
						md5($this->scriptroot.$css),
						get_template_directory_uri().'/'.APP_FOLDER.'/'.$this->scriptroot.'/css/'.$css.'.css',
						false,
						'1.0',
						'all'
					);
				}
			}
			
			return $this;
			
		}// end function css()
		
		/**
		 * Try-catch procedure; end trap
		 * 
		 * @example see 'template trap'
		 * 
		 * @return void
		 * @package OctoMS.com
		 * 
		 * @author Valentino-Jivko Radosavlevici
		 */
		function endtrap()
		{
			$this->bug['status']===TRUE?(print ob_get_clean()):ob_clean();
		}// end function endtrap()
		
		/**
		 * Google Analytics script
		 * 
		 * @param string $id - Google Analytics ID
		 * @param array $custom - Associative array of custom variables; maximum size of 4
		 * @return null
		 * 
		 * @author Valentino-Jivko Radosavlevici
		 */
		function ga($id=null,$custom=array())
		{
			// The ID is a must			
			if (!is_null($id))
			{
				$format = '_gaq.push([\'_setCustomVar\', %s, \'%s\', \'%s\', 3]);'."\n";
				$customVar = '';
				if (is_array($custom) && count($custom) > 0 && array_is_assoc($custom))
				{
					$i = 1;
					foreach ($custom AS $key => $value)
					{
						$customVar .= sprintf(
							$format,
							$i,
							htmlspecialchars($key,ENT_QUOTES),
							htmlspecialchars($value,ENT_QUOTES)
						);
						if ($i == 4) break;
						$i++;
					}
					$customVar .= sprintf($format,5,'domain',DOMAIN);
				}
				
				print '<script type="text/javascript">
				var _gaq = _gaq || [];
				_gaq.push([\'_setAccount\', \''.$id.'\']);
				_gaq.push([\'_setDomainName\', \''.DOMAIN.'\']);
				_gaq.push([\'_setAllowLinker\', true]);
				'.$customVar.'
				_gaq.push([\'_trackPageview\',\''.DOMAIN.$_SERVER['REQUEST_URI'].'\']);
				(function() {
					var ga = document.createElement(\'script\');
					ga.type = \'text/javascript\';
					ga.async = true;
					ga.src = (\'https:\' == document.location.protocol ? \'https://ssl\' : \'http://www\') + \'.google-analytics.com/ga.js\';
					var s = document.getElementsByTagName(\'script\')[0];
					s.parentNode.insertBefore(ga, s);
				})();
				</script>';
			}
		}// end function ga()
		
		/**
		 * Show the header- Title and headline
		 * 
		 * @example
		 * // Display the header
		 * {template}->header();
		 * // Return the header as an object with {name} and {tagline} properties
		 * {template}->header(true);
		 * // Print the site name and tagline
		 * print {template}->header(true)->name;
		 * print {template}->header(true)->tagline;
		 * // Set the title
		 * {template}->header('New title');
		 * // Set the description
		 * {template}->header(null,'New tagline');
		 * // Set both the title and the description
		 * {template}->header('New title','New tagline');
		 * // Use the current title for a tagline
		 * {template}->header(false,null,true);
		 * 
		 * @param bool/mixed $return
		 * @param string/null $tagline
		 * $param string/null $flashTagline
		 * @return null/string 
		 * 
		 * @author Valentino-Jivko Radosavlevici
		 */
		function header($return=false,$tagline=null,$flashTagline=false)
		{
			// Get the settings
			$settings = octoms('settings',OMS_L);
			
			// The only accepted alternative type for $return is string
			if (!is_bool($return))
			{
				// Set the title, if not empty
				if (!is_null($return))
				{
					// Set the new title
					$settings
						// Set to wordpress options
						->_prefix()
						// Change the title
						->set('blogname',strval($return))
						// Revert to the default prefix
						->_prefix(true);
				}
				
				// Set the tagline
				if (!is_null($tagline))
				{
					// Set the new description
					$settings
						// Set to wordpress options
						->_prefix()
						// Change the title
						->set('blogdescription',strval($tagline))
						// Revert to the default prefix
						->_prefix(true);
				}
			}
			else 
			{
				// Return?
				if ($return)
				{
					// Prepare the header
					$header = new stdClass();
					$header->name = get_bloginfo('name');
					$header->tagline = ($flashTagline&&!is_front_page())?wp_title('&raquo;',false):get_bloginfo('description');
					
					// Return the header
					return $header;
				}
				else 
				{
					// Echo the header
					echo tag(
					'h1',
					null,
					(
						(bool)($text = $settings->get('logo_text'))
						?
						// Custom text
						a(
							preg_replace(
								'/\[([^\]]*?)\]/i',
								'<b>$1</b>',
								$text
							),
							home_url(),
							array(
								'class'=>'logo_text'
							)
						)
						:
						// Logo set by the user
						a(
							get_bloginfo('name'),
							home_url()
						)
					)
				).
				tag(
					'h2',
					null,
					(($flashTagline&&!is_front_page())?wp_title('&raquo;',false):get_bloginfo('description'))
				);
				}
			}
			
		}// end function header()
		
		/**
		 * Load the help, if there is one
		 * 
		 * @example 
		 * // Set the title and date options
		 * {template}->help(array('title'=>'Foo','date'=>'Bar'));
		 * // Print the help element
		 * {template}->help();
		 * 
		 * @param array $options - Associative array of options. Both keys and values must be strings.
		 * The following statement "{title}" gets replaced with $options['title'] within the html help file.
		 * @return template_l
		 * 
		 * @author Valentino-Jivko Radosavlevici
		 */
		function help()
		{
			// Append arguments
			if (count($args=func_get_args())>0)
			{
				$this->_set('_help_',$args[0]);
				return $this;
			}
			
			// Controller
			$c = trim(str_replace('actions', '', octoms::$oms_info['controller']),DS);
			
			// Model
			$m = octoms::$oms_info['method'];
			
			// Load the help file
			if (file_exists($f = APP_ROOT.DS.'stages'.DS.'island'.DS.'views'.DS.'help'.DS.$c.'-'.$m.'.html'))
			{
				// Get the title
				$title = (is_null($this->_get1('title'))?ucfirst($this->_conf('method')):$this->_get1('title')).' help';
				
				// Get the file contents
				$c = file_get_contents($f);
					
				// Replace variables with shortcodes
				$data = $this->_get1('_help_');
				if(is_array($data) && count($data)>0)
				{
					// Replace shortcodes
					foreach ($data AS $k=>$v)
					{
						$c = str_replace('{'.$k.'}', $v, $c);
					}
					
					// Replace the title?
					if (isset($data['title'])) $title = $data['title'];
				}
				
				// Load the shortkeys information
				if (file_exists($f = APP_ROOT.DS.'stages'.DS.'island'.DS.'views'.DS.'help'.DS.'#shortkeys.html'))
				{
					$c .= str_replace(
						'{debugger}', 
						(DEBUG_WIZARD?'<li>Ctrl+<b>O</b> - For the OctoMS Debugger.</li>':''), 
						'<hr/>'.file_get_contents($f)
					);
				}
				
				// Print the help interface
				print '<help title="'.$title.'">'.$c.'</help>';
				
			}
			
			// All done
			return $this;
		}// end function help()
		
		/**
		 * Set or display the page's JS scripts
		 * 
		 * @example 
		 * // Enqueue a JS script
		 * {template}->js('foo');
		 * 
		 * @param array $js
		 * @return $this
		 * @package OctoMS.com
		 * 
		 * @author Valentino-Jivko Radosavlevici
		 */
		function js()
		{
			// Enqueue scripts one by one
			if (count($args = func_get_args())>0)
			{
				foreach ($args AS $js)
				{
					wp_enqueue_script(
						md5(APP_FOLDER.'/'.$this->scriptroot.'/js/'.$js.'.js'),
						get_template_directory_uri().'/'.APP_FOLDER.'/'.$this->scriptroot.'/js/'.$js.'.js',
						false,
						'1.0',
						$this->infooter
					);
				}
			}
			
			return $this;
			
		}// end function js()
		
		/**
		 * Append or display the menu
		 * 
		 * @example 
		 * 
		 * @param array $menu
		 * @return $this
		 * @package OctoMS.com
		 * 
		 * @author Valentino-Jivko Radosavlevici
		 */
		function menu($name=null,$options=null,$add=FALSE)
		{
			// Use this as an append function
			if ($add) 
			{
				// Get the menus
				$menus = $this->_get1('menus');
				
				// Append or replace the menu
				if (is_null($menus))
				{
					$menus = array($name=>$options);
				}
				else 
				{
					$menus[$name] = $options;
				}
				
				// Save it
				$this->_set('menus',$menus);
				
				// All done
				return $this;
			}
			// Use this as a view tool
			else 
			{
				// Get the menus
				$menus = $this->_get1('menus');
				
				// Use the default?
				if (is_null($name)) $name = 'default';
				
				// Print the one requested
				if (is_string($name) && isset($menus[$name])) 
				{
					print l(
						$menus[$name],
						null,
						$options
					);
				}
				
				// Return this
				return $this;
			}
			
		}// end function menu()

		/**
		 * Display the theme's menu
		 * 
		 * @param string $name - Menu location
		 * @param array $container - Container ID and Class
		 * @param array $menu - Menu ID and Class
		 * @param bool $select - Wether to show the menu as a select dropdown
		 * @param bool $return - Wether to return the menu
		 * 
		 * @return - False on error, Null if menu is to be echoed, String otherwise
		 * @author Valentino-Jivko Radosavlevici
		 */
		function menu_theme($name=null,$container=null,$menu=null,$select=false,$return=false)
		{
			// The name is mandatory
			if (null === $name) return false;
			
			// Prepare the settings array
			$settings = array(
				'theme_location'  => $name,
				'fallback_cb'	=> false,
				'echo'            => $return?'0':true
			);
			
			// Get the container class and ID
			if (is_array($container))
			{
				if (isset($container['class']))
				{
					$settings['container_class'] = $container['class'];
				}
				if (isset($container['id']))
				{
					$settings['container_id'] = $container['id'];
				}
			}
			if (!isset($settings['container_class']))
			{
				$settings['container_class'] = sprintf('menu-%s-container',$name);
			}
			
			// Get the menu class and ID
			if (is_array($menu))
			{
				if (isset($menu['class']))
				{
					$settings['menu_class'] = $menu['class'];
				}
				if (isset($menu['id']))
				{
					$settings['menu_id'] = $menu['id'];
				}
			}
			
			// Register the menu
			if (!$select)
			{
				return wp_nav_menu($settings);
			}
			else 
			{
				// Prepare the result
				$result = '';
				
				// Find the menu
			    if (($locations = get_nav_menu_locations()) && isset($locations[$name]))
			    {
			    	// Get the page ID
			    	global $wp_query;
			    	$id = @$wp_query->post->ID;
			    	
			    	// Get the menu
			    	$m = wp_get_nav_menu_object($locations[$name]);
			    	
			    	
			    	// Get the depths
			    	$depths = array();
			    	
			    	// Parse the items
			    	if (is_object($m) && property_exists($m, 'term_id'))
			    	{
			    		// Append the select
				    	$result .= sprintf(
				    		'<select onchange="window.location.href=this.value" %s %s>',
				    		(isset($menu['id'])?'id="'.$menu['id'].'"':''),
				    		(isset($menu['class'])?'class="'.$menu['class'].'"':'')
				    	);
			    	
						foreach ((array)wp_get_nav_menu_items($m->term_id) as $key => $item )
						{
							// Calculate the depth
							if ($item->menu_item_parent == '0')
						    {
						    	$depths[$item->ID] = 0;
						    }
						    else 
						    {
						    	if (isset($depths[$item->menu_item_parent]))
						    	{
						    		$depths[$item->ID] = $depths[$item->menu_item_parent] + 1;
						    	}
						    	else 
						    	{
						    		$depths[$item->ID] = 1;
						    	}
						    }
						    
						    // Print the dash
						    $dash = str_pad('',$depths[$item->ID],'-');
						    if (strlen($dash)>0)
						    {
						    	$dash = '|'.str_replace('-','&mdash;',substr($dash, 0, strlen($dash)-1)).'&mdash;&nbsp;';
						    }
						    
						    // Prepare the settings
						    $sel = array(
					    		'value' => htmlspecialchars($item->url,ENT_QUOTES)
					    	);
						    
					    	// Is this page current?
					    	if ($id == $item->object_id)
					    	{
					    		$sel['selected'] = 'selected';
					    	}
						    
						    // Send the result
						    $result .= tag(
						    	'option',
						    	$sel,
						    	$dash.htmlspecialchars($item->title)
						    );
						}
						$result .= '</select>';
			    	}
			    }
			    
			    // Stylize the container
			    $result = tag(
			    	'div',
			    	$container,
			    	$result
			    );
			    
			    // Return the result?
			    if ($return)
			    {
			    	return $result;
			    }
			    // Print it
			    else
			    {
			    	print $result;
			    }
			}
			
		}// end function menu_theme()
		
		/**
		 * Return the current page's title
		 * 
		 * @author Valentino-Jivko Radosavlevici
		 */
		function page_title()
		{
			$result = '';
			switch ($this->page_type())
			{
				case 'tag':
					$result = sprintf('Tag "%s"',get_query_var('tag'));
					break;
				case 'archive':
					$result = sprintf('Archive "%s"',trim(single_month_title(' ',false)));
					break;
				case 'search':
					$result = sprintf('Search "%s"',get_search_query());
					break;
				case 'category':
					$temp = get_the_category();
					$result = sprintf('Category "%s"',get_query_var('category_name'));
					break;
				case 'notfound':
					$result = '404';
					break;
				default:
					$result = wp_title(null,false);
			}
			
			return $result;
			
		}// end function page_title()
		
		/**
		 * Return the current page's type
		 * 
		 * @return string - The current page type:<ul>
		 * <li>tag</li>
		 * <li>archive</li>
		 * <li>search</li>
		 * <li>category</li>
		 * <li>notfound</li>
		 * <li>single</li>
		 * </ul>
		 * @author Valentino-Jivko Radosavlevici
		 */
		function page_type()
		{
			// A tag page
			if (is_tag())
			{
				return 'tag';
			}
			
			// Category page
			if (is_category()) 
			{
				return 'category';
			}
			
			// An archive page
			if (is_archive())
			{
				return 'archive';
			}
			
			// Search page
			if (is_search()) 
			{
				return 'search';
			}
			
			// Not found?
			if (is_404())
			{
				return 'notfound';
			}
			
			// A single page
			return 'single';
			
		}// end function page_type()
		
		/**
		 * Page category class
		 * 
		 * @author Valentino-Jivko Radosavlevici
		 */
		function page_category_class($category=null,$print=true)
		{
			if (is_null($category))
			{
				$temp = get_the_category();
				if(isset($temp[0]))
				{
					$category = $temp[0]->slug;
				}
				else 
				{
					return '';
				}
			}
			
			// Get the saved category images
			$s = octoms('settings',OMS_L)->get('categories');
			if (is_null($s)) $s = array();
			
			// Get the current category
			if (isset($s[$category]) && isset($s[$category]['color']) && isset($s[$category]['type']))
			{
				// Prepare the result
				$result = sprintf(
					'octoms-category l%s c%s',
					$s[$category]['type'] + 1,
					$s[$category]['color'] + 1
				);
				
				if (!$print)
				{
					return $result;
				}
				else 
				{
					print $result;
				}
			}
			
		}// end function page_category_class()
		
		/**
		 * Page category link
		 * 
		 * 
		 * @author Valentino-Jivko Radosavlevici
		 */
		function page_category_url($print=true)
		{
			$temp = get_the_category();
			if(isset($temp[0]))
			{
				$category = $temp[0]->cat_ID;
			}
			else 
			{
				return '';
			}
			
			// Return the link
			if ($print)
			{
				print get_category_link($category);
			}
			else
			{
				return get_category_link($category);
			}
			
		}// end function page_category_url()
		
		/**
		 * Display the "powered by" information and page creation statistics
		 * 
		 * @example $this->powered();
		 * 
		 * @return $this
		 * @package OctoMS.com
		 * 
		 * @author Valentino-Jivko Radosavlevici
		 */
		function powered()
		{			
			octoms('html',OMS_CH);
			// Please do not modify this
			print 'Powered by '.a(
				'DesignJotter',
				'http://DesignJotter.com',
				array(
					'title'=>sprintf(
						'Generated by DesignJotter in %ss @%sMB (WordPress used another %sMB).',
						round(microtime(true)-octoms::$oms_info['start'],3),
						round((memory_get_usage() - octoms::$oms_info['start_memory'])/1048576,3),
						round(octoms::$oms_info['start_memory']/1048576,3)
					),
					'target'=>'_blank'
				)
			). ' version <b>'.WP_OCTOMS_VERSION.
			'</b> (<i>"'.
				a(
					WP_OCTOMS_VERSION_ACRONYM,
					'http://DesignJotter.com/'.strtolower(WP_OCTOMS_VERSION_ACRONYM),
					array(
						'target'=>'_blank'
					)
				).
			'"</i>)';
			
			return $this;
		}// end function powered()
		
		/**
		 * Set or display a template region
		 * 
		 * @example 
		 * // Display the region named 'comments'
		 * {template}->region('comments');
		 * // Set the region named 'comments' with $data
		 * {template}->region('comments',$data);
		 * // Set multiple regions
		 * {template}->regions(array('a'=>'A content','b'=>'B content'));
		 * 
		 * @throws {template}->_bug()
		 * 
		 * @param string $name
		 * @param string/false $content
		 * @param bool/array/string $encapsulate - true for "ferv_{name}" class, array or string for HTML options (like class,id etc.)
		 * @return $this
		 * @package OctoMS.com
		 * 
		 * @author Valentino-Jivko Radosavlevici
		 */
		function region($name='',$content=FALSE,$encapsulate=TRUE)
		{
			if ($content === FALSE)
			{
				if (is_string($name))
				{
					if (isset($this->data['regions'][$name])) 
					{
						if ($encapsulate===true)
						{
							$encapsulate='id="ferv_'.$name.'"';
						}
						elseif ($encapsulate !== FALSE)
						{
							if (is_array($encapsulate))
							{
								$result = "";
								foreach ($encapsulate AS $k => $v)
								{
									$result .= $k.'="'.htmlentities($v,ENT_QUOTES,'UTF-8').'" ';
								}
								$encapsulate = $result;
							}
							elseif (!is_string($encapsulate))
							{
								$encapsulate = '';
							}
						}
						
						print ($encapsulate!==FALSE?'<div '.$encapsulate.'>':'').$this->_shortcode($this->data['regions'][$name]).($encapsulate!==FALSE?'</div>':'');
					}
					else
					{
						$this->_bug('Region "'.$name.'" not set.');
					}
				}
				elseif (is_array($name))
				{
					foreach ($name AS $k => $v)
					{
						$this->region($k,$v);
					}
				}
			}
			elseif(!empty($name))
			{
				$this->data['regions'][$name] = $content;
			}
			
			return $this; 
		}// end function region()
		
		/**
		 * Set scripts root (js and css)
		 * 
		 * @example 
		 * // Revert to the default script root (app/template)
		 * $template->scriptroot();
		 * // Root to the 'island' stage views
		 * $template->scriptroot(true);
		 * // Root to the 'test' widget views
		 * $template->scriptroot('test');
		 * // Root to the 'test' widget 'lightbox' subfolder in views
		 * $template->scriptroot('test','lightbox');
		 * 
		 * @param string $s
		 * @param string $subfolder
		 * @return $template
		 * @author Valentino-Jivko Radosavlevici
		 */
		function scriptroot($s=NULL,$subfolder=null)
		{
			if (!is_null($s))
			{
				if (true === $s)
				{
					$this->scriptroot = 'stages/island/views';
				}
				elseif (is_string($s))
				{
					$this->scriptroot = 'stages/widgets/'.$s.'/views'.(null!==$subfolder?('/'.$subfolder):'');
				}
			}
			else 
			{
				$this->scriptroot = 'template';
			}
			
			return $this;
		}// end function scriptroot()
		
		/**
		 * Display a sidebar
		 * 
		 * @example 
		 * // Display the "left" sidebar
		 * $template->sidebar('left');
		 * 
		 * @param string $id
		 * 
		 * @author Valentino-Jivko Radosavlevici
		 */
		function sidebar($id=null)
		{
			if (!is_null($id) && false !== strpos(WP_SIDEBARS, $id))
			{
				dynamic_sidebar($id);
			}
			
		}// end function sidebar()
		
		/**
		 * Try-catch procedure; snap - catches (a) _bug() issued within the trap
		 * 
		 * @example see 'template trap'
		 * 
		 * @return void
		 * @package OctoMS.com
		 * 
		 * @author Valentino-Jivko Radosavlevici
		 */
		function snap()
		{
			if (!$this->bug['status'])
			{
				ob_clean();$this->bug['status'] = TRUE;
			}
			else
			{
				ob_flush();$this->bug['status'] = FALSE;
			}
		}// end function snap()
		
		/**
		 * Set or display the page title
		 * 
		 * @example 
		 * // Display the page title as text
		 * {template}->title();
		 * // Display the page title as a meta title tag
		 * {template}->title(true);
		 * // Set the page title
		 * {template}->title('Awesome page');
		 * 
		 * @param string $title
		 * @return $this
		 * @package OctoMS.com
		 * 
		 * @author Valentino-Jivko Radosavlevici
		 */
		function title()
		{
			// Use this as an append function
			if (count($args = func_get_args())>0 && $args[0] !== TRUE) 
			{
				array_unshift($args, 'title');
				return call_user_func_array(array($this,'_app'), $args);
			}
			
			// Get the title
			$title = is_null($this->_get1('title'))?ucfirst($this->_conf('method')):$this->_get1('title');
			
			// Print it
			print ((isset($args[0]) && $args[0]===TRUE)?tag('title',null,htmlspecialchars($title)):$title)."\n\t";
						
			return $this;
			
		}// end function title()
		
		/**
		 * Try-catch procedure; trap
		 * 
		 * @example 
		 * // Use within a template file; similar to the try{}catch(Exception $e){} block
		 * $this->trap();
		 * // Try to display the 'test' region
		 * # $this->region('test');
		 * // Has a _bug() been issued?
		 * $this->snap();
		 * // Print the template exception message and code
		 * # print $this->bug['message'].$this->bug['code'];
		 * $this->endtrap();
		 * 
		 * @param 
		 * @return 
		 * @package OctoMS.com
		 * 
		 * @author Valentino-Jivko Radosavlevici
		 */
		function trap()
		{
			ob_start();$this->bug = array('status'=>true,'message'=>'','code'=>'');
		}// end function trap()
		
		/**
		 * Display a widget.<br/>
		 * You can use the following properties in your widget <b>controller</b>:<ul>
		 * <li>__args</li>
		 * <li>__content</li>
		 * </ul>
		 * 
		 * @example 
		 * // Load the method 'method1' from the widget 'w1'
		 * {template}->widget('w1'[,'method1'][,array('value1','value2')][,'Foo bar']);
		 * // Or use associative argument calls
		 * {template}->widget('w1','method1',array('arg1'=>'value1','arg3'=>'value2'),'Foo bar');
		 * 
		 * @throws {template}->_bug();
		 * 
		 * @param string $widget
		 * @param string $method
		 * @param array $args
		 * @param string $content
		 * @param bool $return
		 * @return mixed - the result of the requested method
		 * @package OctoMS.com
		 * 
		 * @author Valentino-Jivko Radosavlevici
		 */
		function widget($widget,$method=NULL,$args=array(),$content=null,$return=false)
		{
			// The class name
			$controller = 'w_'.($widget = strval($widget));
			
			if ($return)
			{
				// Start the buffer
				ob_start();
			}
			
			// Fetch the object
			if(!isset(octoms::$oms_objects[$controller]))
			{
				// Load the Controller
				if (file_exists($f = WIDGETS.DS.$widget.DS.'controllers'.DS.$controller.EXT))
				{
					require_once $f;
					// Load the controller
					if (!class_exists($controller))
					{
						return $this->_bug('Widget "'.$widget.'" expects controller class "'.$controller.'{}".', 1);
					}
					else 
					{
						octoms::$oms_objects[$controller] = new $controller;
					}
					
					// Is there a model?
					if (file_exists($f = WIDGETS.DS.$widget.DS.'models'.DS.$controller.EXT))
					{
						require_once $f;
						$model = $controller.'_m';
						
						if (!class_exists($model)) 
						{
							$this->_bug('Widget "'.$widget.'" expects model class "'.$model.'{}".', 2);
						}
						else 
						{
							octoms::$oms_objects[$controller]->model = new $model;
						}
					}
					
					// Bind all the objects to this widget
					foreach (array_keys(octoms::$oms_objects) AS $key)
					{
						if (strpos($key, 'w_') === FALSE)
						{
							$obj = substr($key,0,strpos($key, '_'));
							
							// Bind objects to the controller
							octoms::$oms_objects[$controller]->$obj = octoms::$oms_objects[$key];
							
							// Bind objects to the model (if set)
							if (isset(octoms::$oms_objects[$controller]->model)) octoms::$oms_objects[$controller]->model->$obj = octoms::$oms_objects[$key];
						}
					}
					
				}
				else 
				{
					return $this->_bug('Widget "'.$widget.'" expects controller file "'.$controller.EXT.'".', 3);
				}
			}
			
			// Prepare the JS and CSS? Call this before $this->js() and $this->css() in your template
			if (!is_bool($method))
			{
				// Set the method
				$method = empty($method)?'index':strval($method);
				
				// Don't allow access to private methods
				if (0===strpos($method, '_')) return false;
				
				// Is it defined?
				if(!method_exists(octoms::$oms_objects[$controller], $method))
				{
					return $this->_bug('Method "'.$method.'()" not found in widget "'.$widget.'".', 4);
				}
				
				// Save the complete arguments
				octoms::$oms_objects[$controller] -> __args = $args;
				
				// Reorder the elements
				if (array_is_assoc($args))
				{
					$r = new ReflectionMethod($controller, $method);
					$a = array();
					foreach ($r->getParameters() AS $param)
					{
						$name = $param->getName();
						$a[] = isset($args[$name])?$args[$name]:null;
					}
					$args = $a;
				}
				
				// Save the content
				octoms::$oms_objects[$controller] -> __content = $content;
				
				// Return the result as text?
				if ($return)
				{
					// Call the method
					call_user_func_array(array(octoms::$oms_objects[$controller],$method), (array)$args);
					
					// Return the result
					return ob_get_clean();
				}
				else 
				{
					// Call the method
					return call_user_func_array(array(octoms::$oms_objects[$controller],$method), (array)$args);
				}
			}
			
		}// end function widget()
			
	}// end class template_l
	
	
/* End Of File <template.inc> */